PMSM Sensorless Field Oriented Control using the ATXmega16D4 Atmel Studio 6 (Version: 6.0.1938 - Service Pack 1) using AVR GCC Compiler -02 optimization Installed Packages: AVRGCC - 3.4.0.65 AVR Toolchain 8 Bit Version: 3.4.0.663 - GCC 4.6.2 Program Memory Usage : 6688 bytes 32.7 % Full Data Memory Usage : 153 bytes 7.5 % Full. More...
#include <stdint.h>#include <avr/io.h>#include <avr/pgmspace.h>#include <avr/interrupt.h>#include <avr/eeprom.h>Defines | |
| #define | PWM_PRESCALER 4 |
| #define | PWM_MAX 256 |
| #define | PWM_HALF 127 |
| #define | PWM_DB 24 |
| #define | V_MAX 123 |
| #define | I_MAX 120 |
| #define | PWM_PERIODS 960 |
| #define | TXD_PIN PIN3_bm |
| #define | TxD_pin_0 PORTD_OUTCLR = TXD_PIN |
| #define | TxD_pin_1 PORTD_OUTSET = TXD_PIN |
| #define | TxD_pin_out PORTD_DIRSET |= TXD_PIN |
| #define | TxD_pin_totem PORTD_PIN3CTRL |= PORT_OPC_TOTEM_gc |
| #define | RXD_PIN PIN2_bm |
| #define | RXD_pin_test (PORTD_IN & RXD_PIN) |
| #define | RXD_PIN_0 0 |
| #define | RXD_PIN_1 RXD_PIN |
| #define | TEST_PIN PIN6_bm |
| #define | TEST_pin_lo PORTC_OUTCLR = TEST_PIN |
| #define | TEST_pin_hi PORTC_OUTSET = TEST_PIN |
| #define | TEST_pin_out PORTC_DIRSET |= TEST_PIN |
| #define | TEST_pin_totem PORTC_PIN6CTRL |= PORT_OPC_TOTEM_gc |
| #define | ADC_PRESCALER 4 |
| #define | ADC_MUX_bm 0x3F |
| #define | ADC_MUX_X 0 |
| #define | ADC_MUX_VBUS (ADC_CH_MUXPOS2_bm | ADC_CH_MUXPOS1_bm) |
| #define | ADC_MUX_I (ADC_CH_MUXPOS2_bm) |
| #define | HALF_SCALE 128 |
| #define | TRIGGER_OFFSET 1 |
| #define | DEAD_TIME (PWM_DB/PWM_PRESCALER) |
| #define | CURRENT_SETTLING_TIME 14 |
| #define | SAMPLE_HOLD_TIME 11 |
| #define | SAMPLE_1_OFFSET (SAMPLE_HOLD_TIME) |
| #define | SAMPLE_2_OFFSET (TRIGGER_OFFSET + DEAD_TIME + CURRENT_SETTLING_TIME) |
| #define | SAMPLE_WINDOW (SAMPLE_1_OFFSET + SAMPLE_2_OFFSET) |
| #define | ONE_OVER_THREE 85 |
| #define | TWO_OVER_THREE 171 |
| #define | ONE_OVER_SQRT_THREE 148 |
| #define | TWO_OVER_SQRT_THREE 148 |
| #define | SQRT_THREE_OVER_TWO 222 |
| #define | VARIABLE_TABLE_SIZE 16 |
| #define | EEPROM_TABLE_SIZE 32 |
| #define | HEADER_SIZE 64 |
| #define | MESSAGE_SIZE (HEADER_SIZE + VARIABLE_TABLE_SIZE + EEPROM_TABLE_SIZE +1) |
| #define | v_a_display variable_table[0] |
| #define | v_b_display variable_table[1] |
| #define | i_a_display variable_table[2] |
| #define | i_b_display variable_table[3] |
| #define | u_a_display variable_table[4] |
| #define | ir_a_display variable_table[5] |
| #define | l_didt_a_display variable_table[6] |
| #define | e_a_display variable_table[7] |
| #define | i_d_display variable_table[8] |
| #define | i_q_display variable_table[9] |
| #define | e_d_display variable_table[10] |
| #define | v_bus variable_table[11] |
| #define | speed variable_table[12] |
| #define | theta variable_table[13] |
| #define | osc_error variable_table[14] |
| #define | counter variable_table[15] |
| #define | v_bus_min variable_table[0 + VARIABLE_TABLE_SIZE] |
| #define | osc_cal_adj variable_table[1 + VARIABLE_TABLE_SIZE] |
| #define | data_watch variable_table[2 + VARIABLE_TABLE_SIZE] |
| #define | mode variable_table[3 + VARIABLE_TABLE_SIZE] |
| #define | input_cmd variable_table[4 + VARIABLE_TABLE_SIZE] |
| #define | s_reg_rate variable_table[5 + VARIABLE_TABLE_SIZE] |
| #define | s_reg_scaling variable_table[6 + VARIABLE_TABLE_SIZE] |
| #define | s_error_limit variable_table[7 + VARIABLE_TABLE_SIZE] |
| #define | s_k_scaling variable_table[8 + VARIABLE_TABLE_SIZE] |
| #define | s_kp variable_table[9 + VARIABLE_TABLE_SIZE] |
| #define | s_ki variable_table[10 + VARIABLE_TABLE_SIZE] |
| #define | i_limit variable_table[11 + VARIABLE_TABLE_SIZE] |
| #define | i_reg_scaling variable_table[12 + VARIABLE_TABLE_SIZE] |
| #define | i_error_limit variable_table[13 + VARIABLE_TABLE_SIZE] |
| #define | i_k_scaling variable_table[14 + VARIABLE_TABLE_SIZE] |
| #define | i_kp variable_table[15 + VARIABLE_TABLE_SIZE] |
| #define | i_ki variable_table[16 + VARIABLE_TABLE_SIZE] |
| #define | v_limit variable_table[17 + VARIABLE_TABLE_SIZE] |
| #define | speed_scale variable_table[18 + VARIABLE_TABLE_SIZE] |
| #define | speed_min variable_table[19 + VARIABLE_TABLE_SIZE] |
| #define | speed_max variable_table[20 + VARIABLE_TABLE_SIZE] |
| #define | p_reg_scaling variable_table[21 + VARIABLE_TABLE_SIZE] |
| #define | p_error_limit variable_table[22 + VARIABLE_TABLE_SIZE] |
| #define | p_k_scaling variable_table[23 + VARIABLE_TABLE_SIZE] |
| #define | p_kp variable_table[24 + VARIABLE_TABLE_SIZE] |
| #define | p_ki variable_table[25 + VARIABLE_TABLE_SIZE] |
| #define | p_gravity variable_table[26 + VARIABLE_TABLE_SIZE] |
| #define | u_scaling variable_table[27 + VARIABLE_TABLE_SIZE] |
| #define | r_scaling variable_table[28 + VARIABLE_TABLE_SIZE] |
| #define | r_phase variable_table[29 + VARIABLE_TABLE_SIZE] |
| #define | l_scaling variable_table[30 + VARIABLE_TABLE_SIZE] |
| #define | l_phase variable_table[31 + VARIABLE_TABLE_SIZE] |
Functions | |
| void | init_oscillator (void) |
| Initializes Oscillator for 32MHz operation. | |
| void | init_test_pin (void) |
| Initializes pin for Code testing function. | |
| void | init_pwm (void) |
| Initializes Port C Timer 0 as Three Phase PWM output with Deadtime. | |
| void | init_adc (void) |
| Initializes ADC. | |
| void | init_uart (void) |
| Initializes UART. | |
| void | init_eventsys (void) |
| Initializes Event System. | |
| void | read_eeprom (void) |
| Reads EEPROM values. | |
| void | write_eeprom (void) |
| Writes EEPROM values. | |
| void | read_oscillator_cal (void) |
| Reads Oscillator calibration value. | |
| void | write_oscillator_cal (void) |
| Writes Oscillator calibration value. | |
| void | test_oscillator (void) |
| Tests accuracy of Oscillator. | |
| void | calibrate_current (void) |
| Current Sense Calibration. | |
| void | init_interrupts (void) |
| Enable interrupts. | |
| ISR (TCC0_CCD_vect) | |
| Interrupt Service Routine for FOC. | |
| int | main (void) |
| Main. | |
Variables | |
| const int8_t sine_table[256] | PROGMEM |
| uint8_t | pwm_counter = 0 |
| uint16_t | byte_timeout |
| uint8_t | data_txd |
| uint8_t | data_rxd |
| uint8_t | data_toggle |
| uint8_t | count_dir |
| uint8_t | valid_byte |
| uint8_t | eeprom_number |
| uint8_t | motor_off |
| uint8_t | i_sample_offset |
| uint8_t | i_sample_1 |
| uint8_t | i_sample_2 |
| uint8_t | sample_state_1 |
| uint8_t | sample_state_2 |
| uint8_t | window_1 |
| uint8_t | window_2 |
| uint8_t | correction_1 |
| uint8_t | correction_2 |
| uint8_t | pwm_1 |
| uint8_t | pwm_2 |
| uint8_t | pwm_3 |
| uint8_t | pwm_a_comp |
| uint8_t | pwm_b_comp |
| uint8_t | pwm_c_comp |
| uint8_t | adc_user_channel = 0 |
| uint8_t | adc_user_sample |
| int8_t | sin_theta |
| int8_t | cos_theta |
| int8_t | i_d |
| int8_t | i_q |
| int8_t | i_alpha |
| int8_t | i_beta |
| int8_t | i_a |
| int8_t | i_b |
| int8_t | i_c |
| int8_t | i_a_s |
| int8_t | i_b_s |
| int8_t | i_c_s |
| int8_t | i_a_last |
| int8_t | i_b_last |
| int8_t | i_c_last |
| int8_t | v_d |
| int8_t | v_q |
| int8_t | v_alpha |
| int8_t | v_beta |
| int8_t | v_a |
| int8_t | v_b |
| int8_t | v_c |
| int8_t | u_a |
| int8_t | u_b |
| int8_t | u_c |
| int8_t | ir_a |
| int8_t | ir_b |
| int8_t | ir_c |
| int8_t | l_didt_a |
| int8_t | l_didt_b |
| int8_t | l_didt_c |
| int8_t | e_a |
| int8_t | e_b |
| int8_t | e_c |
| int8_t | e_alpha |
| int8_t | e_beta |
| int8_t | e_d |
| int8_t | e_q |
| uint8_t | pwm_a |
| uint8_t | pwm_b |
| uint8_t | pwm_c |
| uint8_t | sample_trigger |
| uint8_t | pwm_state |
| int16_t | p_integral |
| int16_t | p_output_min |
| int16_t | p_output_max |
| uint8_t | s_reg_count |
| int16_t | s_integral |
| int16_t | s_output_min |
| int16_t | s_output_max |
| int8_t | i_d_ref |
| int8_t | i_q_ref |
| int16_t | i_d_integral |
| int16_t | i_q_integral |
| int16_t | i_output_max |
| uint8_t | input_ref |
| int16_t | error |
| int16_t | comp_ki |
| int16_t | output |
| uint16_t | theta_int |
| uint8_t | theta_90 |
| uint16_t | osc_cal |
| uint16_t | table_counter = 0 |
| uint8_t | variable_table [VARIABLE_TABLE_SIZE+EEPROM_TABLE_SIZE] |
PMSM Sensorless Field Oriented Control using the ATXmega16D4 Atmel Studio 6 (Version: 6.0.1938 - Service Pack 1) using AVR GCC Compiler -02 optimization Installed Packages: AVRGCC - 3.4.0.65 AVR Toolchain 8 Bit Version: 3.4.0.663 - GCC 4.6.2 Program Memory Usage : 6688 bytes 32.7 % Full Data Memory Usage : 153 bytes 7.5 % Full.
| void calibrate_current | ( | void | ) |
Current Sense Calibration.
Measures the DC offset of the current sense shunt and the resistive divider that biases the shunt voltage above ground when the current is zero. The offset value is used in all current reconstruction calculations.
| void init_adc | ( | void | ) |
Initializes ADC.
ADC is initialized in single ended mode, Left Aligned for 8 bit values Using the 1V internal reference. The conversion is triggered by the port C timer 0 channel D through the event system.
| void init_eventsys | ( | void | ) |
Initializes Event System.
Configures Event System Channel 0 to trigger an ADC conversion off of Compare D Timer/Counter C0. This is used for timing ADC samples for single shunt current reconstruction. The event system signal is brought out to Port D pin 7, used in code development. This can be disabled if the pin needs to be re purposed.
| void init_interrupts | ( | void | ) |
Enable interrupts.
Enables the Timer 0 Port C interrupt for Capture/Compare Channel D set to the highest level. Then enables all interrupts levels.
| void init_oscillator | ( | void | ) |
Initializes Oscillator for 32MHz operation.
This function enables the 32MHz internal oscillator then waits for the oscillator to be ready, then switches over the system clock to 32MHz.
| void init_pwm | ( | void | ) |
Initializes Port C Timer 0 as Three Phase PWM output with Deadtime.
PWM is configured for 31.25kHz operating frequency, 8-bit resolution 32MHz / 4 prescaler / 256 = 31.25kHz Channels A,B, and C along with the AWEX for deadtime to generate three phase PWM. Channel D is used to trigger the ADC, through the event system, for single shunt current reconstruction. Edge aligned PWM is used because it requires the least amount of PWM modification for the ADC sample window.
| void init_test_pin | ( | void | ) |
Initializes pin for Code testing function.
Test pin is used on a spare pin to look at code timing using an oscilloscope. This is only for Debugging and benchmarking code TEST_pin_hi; and TEST_pin_lo; are inserted in code to set the pin high and low.
| void init_uart | ( | void | ) |
Initializes UART.
The UART is set up for bi directional 115,200 baud to match the maximum standard COM port frequency. The UART is polled in the PWM ISR that makes up the FOC control loop. THe UARt is used for communication to the PC based Atmel Motor Control Configuration Utility.
| ISR | ( | TCC0_CCD_vect | ) |
Interrupt Service Routine for FOC.
This is the main control loop for all Field Oriented Control functions and communication with the Motor Control Configuration Utility.
| int main | ( | void | ) |
Main.
Performs all installation function calls then sits waiting for ISR
| void read_eeprom | ( | void | ) |
Reads EEPROM values.
EEPROM values are used for configuration of motor parameters These values are configured and updated from the PC based Motor Control Configuration Utility
| void read_oscillator_cal | ( | void | ) |
Reads Oscillator calibration value.
Reads in factory calibration value for 32Mhz oscillator and stores in RAM.
| void test_oscillator | ( | void | ) |
Tests accuracy of Oscillator.
Compares to USB to UART bridge oscillator to internal oscillator PC sends a 0 byte at 300 baud, for a 30ms period count the number of PWM periods. 30ms/31.25us = 960 periods
| void write_eeprom | ( | void | ) |
Writes EEPROM values.
EEPROM values are used for configuration of motor parameters These values are configured and updated from the PC based Motor Control Configuration Utility
| void write_oscillator_cal | ( | void | ) |
Writes Oscillator calibration value.
Writes calibration value for 32Mhz oscillator.
1.8.0